#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <memory>
#include <unistd.h>

using namespace std;


using TaskFunc = std::function<void()>;
using ReleaseFunc = function<void()>;
class TimerTask
{
private:
    uint64_t _id;           //定时器任务对象ID
    uint32_t _timeout;      //定时任务超时时间
    bool _canceled;         //定时任务取消标记，true 为取消定时任务，false 为不取消
    TaskFunc _task_cb;      //定时器对象要执行的定时任务
    ReleaseFunc _release;   //用于删除TimerWheel中保存的定时器对象信息
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc& cb)
        :_id(id), _timeout(delay), _task_cb(cb), _canceled(false)
        {}
    
    ~TimerTask() 
    {
        if(_canceled == false)
            _task_cb(); 
        
        _release();
    }
    
    void SetRelease(const ReleaseFunc& cb) { _release = cb; }   //设置删除定时器对象信息的 回调函数
    uint32_t DelayTime() { return _timeout; }                   //返回超时时间
    void cancel() { _canceled = true; }                         //将定时器标记为取消
};

class TimerWheel
{
private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
            { _timers.erase(it); }
    }
    private:
    using PtrTask = shared_ptr<TimerTask>;
    using WeakTack = weak_ptr<TimerTask>;
    int _tick;          //当前的秒针，走到哪释放哪里的任务
    int _capacity;      //表盘的最大数量 --其实就是最大延迟时间
    vector<vector<PtrTask>> _wheel;
    unordered_map<uint64_t, WeakTack> _timers;
    
public:
    TimerWheel():_tick(0), _capacity(60),_wheel(_capacity) {}
    // ~TimerWheel(){ }
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb)     //添加定时任务
    {
        PtrTask pt(new TimerTask(id, delay, cb));
        pt->SetRelease(bind(&TimerWheel::RemoveTimer, this, id));
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTack(pt);

    }
    void TimerRefresh(uint64_t id)                                     //刷新/延迟定时任务
    {
        // 通过保存的定时器对象的weak_ptr构造一个shared_ptr出来，添加到轮子中
        auto it = _timers.find(id);
        if(it == _timers.end())
            { return; } //没找到定时器任务，没办法刷新/延迟
        PtrTask pt = it->second.lock();         //lock获取weak_ptr管理的对象对应的shared_ptr
        int delay = pt->DelayTime();
        int pos = (_tick + delay ) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void Timercancel(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
            { return; } 
        PtrTask pt = it->second.lock();         //lock获取weak_ptr管理的对象对应的shared_ptr
        if(pt)
            pt->cancel();
    }
    // 这个函数应该每秒钟被执行一次，相当于秒针向后走了一步
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();      //清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }

};

class test
{
public:
    test() { cout << "构造" << endl;}
    ~test() { cout << "析构" << endl;}
};
void remover(test *t)
{
    delete t;
}
int main()
{
    TimerWheel tw;
    test *t = new test();

    tw.TimerAdd(111, 5, bind(remover, t));

    for(int i = 0; i< 5; ++i)
    {
        sleep(1);
        tw.TimerRefresh(111);
        tw.RunTimerTask();
        cout << "刷新任务，需要5秒后才会销毁" << endl;
    }
    tw.Timercancel(111);
    while(true)
    {
        cout << "----------------" << endl;
        tw.RunTimerTask();
        sleep(1);
    }

    return 0;
}